'use strict';

import { existsSync, readFileSync } from 'fs';
import { join, basename } from 'path';

interface Asset {
    displayName: string;
    file: string;
    imported: boolean;
    importer: string;
    invalid: boolean;
    isDirectory: boolean;
    library: {
        [extname: string]: string;
    };
    name: string;
    url: string;
    uuid: string;
    visible: boolean;
    subAssets: {
        [id: string]: Asset;
    };
}

interface Meta {
    files: string[];
    imported: boolean;
    importer: string;
    subMetas: {
        [id: string]: Meta;
    };
    userData: {
        [key: string]: any;
    };
    uuid: string;
    ver: string;
}

type Selector<$> = { $: Record<keyof $, HTMLElement> } & { dispatch(str: string): void, assetList: Asset[], metaList: Meta[] };

export const $ = {
    'code': '#code',
    'section': '#section',
    'deps': '#deps',
    'depsInput': '#depsInput',
    'autoExclude': '#autoExclude',
    'cantBeDepend': '#cantBeDepend',
    'cantDependOthers': '#cantDependOthers',
    'excludeDepsNode': '#excludeDepsNode',
    'excludeDepsInput': '#excludeDepsInput',
    'bundleReleaseAction': '#bundleReleaseAction',
};

// 添加bundle的自定义依赖，不知道怎么使用list引用 Assets，先用input代替
export const template = `
<ui-section id="deps" header="Bundle依赖扩展" expand>
    <ui-prop>
        <ui-label slot="label" value="Bundle释放方式"></ui-label>
        <ui-select slot="content" id="bundleReleaseAction">
            <option value="0">Default (默认， 根据开关决定是否释放)</option>
            <option value="1">DontRelease (不释放， 设置setAutoRelease(false))</option>
            <option value="2">DontCache (不缓存，直接释放)</option>
        </ui-select>
    </ui-prop>
    <ui-prop>
        <ui-label slot="label" tooltips="选中时，若无外部Bundle依赖该Bundle，则自动排除">是否自动排除</ui-label>
        <ui-checkbox slot="content" id="autoExclude"></ui-checkbox>
    </ui-prop>
    <ui-prop>
        <ui-label slot="label" tooltips="选中时，导出后检测被依赖则报错">不能被依赖</ui-label>
        <ui-checkbox slot="content" id="cantBeDepend"></ui-checkbox>
    </ui-prop>
    <ui-prop id="excludeDepsNode">
        <ui-label>输入排除的依赖Assets Bundle</ui-label>
        <ui-input id="excludeDepsInput" tooltip="有多个依赖包时使用逗号隔开"></ui-input>
    </ui-prop>
    <ui-prop>
        <ui-label slot="label" tooltips="选中时，导出后检测有外部依赖则报错">不能依赖外部</ui-label>
        <ui-checkbox slot="content" id="cantDependOthers"></ui-checkbox>
    </ui-prop>
    <!--ui-button @click="addDependency">添加资源</ui-button-->
    <!--ui-list id="list" v-for="(dep, index) in extDepList" :key="index">
        <ui-item>{{ dep }}</ui-item>
        <ui-button @click="removeDependency(index)">删除</ui-button>
    </ui-list-->
    <ui-prop>
        <ui-label>输入额外依赖的Assets Bundle</ui-label>
        <ui-input id="depsInput" tooltip="有多个依赖包时使用逗号隔开"></ui-input>
    </ui-prop>
</ui-section>
<ui-section id="section" header="文件夹说明" expand>
    <ui-code id="code"></ui-code>
</ui-section>
`;

type PanelThis = Selector<typeof $> & { currentMeta?: Meta, currentUrl:string };

const innerBundles: string[] = [
    'app-admin',
    'app-model',
    'app-control',
    'app-controller',
    'app-manager',
];

export function updateMetaDeps(this: PanelThis, asset: Asset, meta: Meta): boolean {
    if (!meta.userData['isBundle']) return false;
    const bundleName = meta.userData['bundle_name'] ?? basename(asset.url).replace('.meta', '');;
    if (bundleName === 'resources') return false;
    const input = this.$.depsInput as any;
    this.$.deps.hidden = false;
    input.value = meta.userData['dep_ext'] ?? "";
    this.currentUrl = asset.url;
    this.currentMeta = meta;
    const checkBox = this.$.autoExclude as any;
    checkBox.value = meta.userData['auto_exclude'] ?? false;
    const checkBox1 = this.$.cantBeDepend as any;
    checkBox1.value = meta.userData['cannot_be_dep'] ?? false;
    const excludeNode = this.$.excludeDepsNode as any;
    excludeNode.hidden = !checkBox1.value;
    const excludeInput = this.$.excludeDepsInput as any;
    excludeInput.value = meta.userData['exclude_deps'] ?? "";
    const checkBox2 = this.$.cantDependOthers as any;
    checkBox2.value = meta.userData['cannot_dep_others'] ?? false;
    const releaseAction = this.$.bundleReleaseAction as any;
    if (innerBundles.indexOf(bundleName) >= 0) {
        releaseAction.value = 1;
        releaseAction.disabled = true;
    } else {
        releaseAction.value = meta.userData['release_action'] ?? 0;
        releaseAction.disabled = false;
    }
    return true;
}

export function update(this: PanelThis, assetList: Asset[], metaList: Meta[]) {
    this.assetList = assetList;
    this.metaList = metaList;

    if (assetList.length === 0) {
        this.$.code.innerHTML = '';
    } else {
        this.$.code.innerHTML = assetList
            .filter((asset) => {
                const mdFile = join(asset.file, `.${asset.name}.md`);
                return existsSync(mdFile);
            })
            .map((asset) => {
                const mdFile = join(asset.file, `.${asset.name}.md`);
                const mdStr = readFileSync(mdFile, 'utf-8');
                return assetList.length > 1 ? `${asset.url}:\n ${mdStr}` : mdStr;
            })
            .join('\n') || '';
    }

    if (this.$.code.innerHTML === '') {
        this.$.section.hidden = true;
    } else {
        this.$.section.hidden = false;
    }

    // 添加bundle的自定义依赖
    this.currentMeta = null;
    this.currentUrl = null;
    if (assetList.length === 1) { // 不支持multiple
        if (updateMetaDeps.call(this, assetList[0], metaList[0])) {
            return;
        }
    }
    this.$.deps.hidden = true;
}

async function saveMata(meta: Meta): Promise<void> {
    const uuid = meta.uuid;
    await Editor.Message.request('asset-db', 'save-asset-meta', uuid, JSON.stringify(meta));
}

export function ready(this: PanelThis) {
    this.$.depsInput.addEventListener('confirm', ()=>{
        if (!this.currentMeta) return;
        const input = this.$.depsInput as any;
        this.currentMeta.userData['dep_ext'] = input.value;
        saveMata(this.currentMeta);
    })
    this.$.excludeDepsInput.addEventListener('confirm', ()=>{
        if (!this.currentMeta) return;
        const input = this.$.excludeDepsInput as any;
        this.currentMeta.userData['exclude_deps'] = input.value;
        saveMata(this.currentMeta);
    })
    this.$.autoExclude.addEventListener('confirm', ()=>{
        if (!this.currentMeta) return;
        this.currentMeta.userData['auto_exclude'] = !this.currentMeta.userData['auto_exclude'] ? true : undefined;
        saveMata(this.currentMeta);
    })
    this.$.cantBeDepend.addEventListener('confirm', ()=>{
        if (!this.currentMeta) return;
        this.currentMeta.userData['cannot_be_dep'] = !this.currentMeta.userData['cannot_be_dep'] ? true : undefined;
        saveMata(this.currentMeta);
    })
    this.$.cantDependOthers.addEventListener('confirm', ()=>{
        if (!this.currentMeta) return;
        this.currentMeta.userData['cannot_dep_others'] = !this.currentMeta.userData['cannot_dep_others'] ? true : undefined;
        saveMata(this.currentMeta);
    })
    this.$.bundleReleaseAction.addEventListener('confirm', (e: any) => {
        if (!this.currentMeta) return;
        const value = Number(e.target.value);
        this.currentMeta.userData['release_action'] = value;
        saveMata(this.currentMeta);
    });
}

export function close(this: PanelThis,) {
    // TODO something
}